4 // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
6 // The use and distribution terms for this software are contained in the file
7 // named license.txt, which can be found in the root of this distribution.
8 // By using this software in any fashion, you are agreeing to be bound by the
9 // terms of this license.
11 // You must not remove this notice, or any other, from this software.
16 namespace Microsoft
.JScript
{
19 using System
.Collections
;
20 using System
.Reflection
;
21 using System
.Reflection
.Emit
;
24 internal sealed class TypeExpression
: AST
{
25 internal AST expression
;
26 internal bool isArray
;
28 private bool recursive
;
29 private IReflect cachedIR
;
31 internal TypeExpression(AST expression
)
32 : base(expression
.context
) {
33 this.expression
= expression
;
36 this.recursive
= false;
38 if (expression
is Lookup
){
39 String name
= expression
.ToString();
40 Object ptype
= Globals
.TypeRefs
.GetPredefinedType(name
);
42 this.expression
= new ConstantWrapper(ptype
, expression
.context
);
46 internal override Object
Evaluate(){
47 return this.ToIReflect();
50 internal override IReflect
InferType(JSField inference_target
){
51 return this.ToIReflect();
54 // has to be called after partially evaluate
55 internal bool IsCLSCompliant(){
56 Object
value = this.expression
.Evaluate();
57 return TypeExpression
.TypeIsCLSCompliant(value);
60 internal override AST
PartiallyEvaluate(){
62 if (this.expression
is ConstantWrapper
) return this;
63 this.expression
= new ConstantWrapper(Typeob
.Object
, this.context
);
66 Member member
= this.expression
as Member
;
68 //Dealing with a qualified name. See if there is a type/class with such a name, bypassing normal scope lookup.
69 Object type
= member
.EvaluateAsType();
71 this.expression
= new ConstantWrapper(type
, member
.context
);
75 this.recursive
= true;
76 this.expression
= this.expression
.PartiallyEvaluate();
77 this.recursive
= false;
78 if (this.expression
is TypeExpression
)
80 //Make sure that the expression represents a Type
82 if (this.expression
is ConstantWrapper
){
83 Object val
= this.expression
.Evaluate();
85 this.expression
.context
.HandleError(JSError
.NeedType
);
86 this.expression
= new ConstantWrapper(Typeob
.Object
, this.context
);
89 t
= Globals
.TypeRefs
.ToReferenceContext(val
.GetType());
90 Binding
.WarnIfObsolete(val
as Type
, this.expression
.context
);
92 if (this.expression
.OkToUseAsType())
93 t
= Globals
.TypeRefs
.ToReferenceContext(this.expression
.Evaluate().GetType());
95 this.expression
.context
.HandleError(JSError
.NeedCompileTimeConstant
);
96 this.expression
= new ConstantWrapper(Typeob
.Object
, this.expression
.context
);
100 if (t
== null || (t
!= Typeob
.ClassScope
&& t
!= Typeob
.TypedArray
&& !Typeob
.Type
.IsAssignableFrom(t
))){
101 this.expression
.context
.HandleError(JSError
.NeedType
);
102 this.expression
= new ConstantWrapper(Typeob
.Object
, this.expression
.context
);
107 internal IReflect
ToIReflect(){
108 if (!(this.expression
is ConstantWrapper
))
109 this.PartiallyEvaluate();
110 IReflect result
= this.cachedIR
;
111 if (result
!= null) return result
;
112 Object
value = this.expression
.Evaluate();
113 if (value is ClassScope
|| value is TypedArray
|| this.context
== null)
114 result
= (IReflect
)value;
116 result
= Convert
.ToIReflect((Type
)value, this.Engine
);
118 return this.cachedIR
= new TypedArray(result
, this.rank
);
120 return this.cachedIR
= result
;
123 internal Type
ToType(){
124 if (!(this.expression
is ConstantWrapper
))
125 this.PartiallyEvaluate();
126 Object
value = this.expression
.Evaluate();
128 if (value is ClassScope
)
129 result
= ((ClassScope
)value).GetTypeBuilderOrEnumBuilder();
130 else if (value is TypedArray
)
131 result
= Convert
.ToType((TypedArray
)value);
133 result
= Globals
.TypeRefs
.ToReferenceContext((Type
)value);
135 return Convert
.ToType(TypedArray
.ToRankString(this.rank
), result
);
140 internal override void TranslateToIL(ILGenerator il
, Type rtype
){
141 this.expression
.TranslateToIL(il
, rtype
);
144 internal override void TranslateToILInitializer(ILGenerator il
){
145 this.expression
.TranslateToILInitializer(il
);
148 internal static bool TypeIsCLSCompliant(Object type
){
149 if (type
is ClassScope
)
150 return ((ClassScope
)type
).IsCLSCompliant();
151 else if (type
is TypedArray
){
152 Object et
= ((TypedArray
)type
).elementType
;
153 if (et
is TypedArray
|| (et
is Type
&& ((Type
)et
).IsArray
)) return false;
154 return TypeExpression
.TypeIsCLSCompliant(et
);
158 if (t
== Typeob
.Boolean
||
161 t
== Typeob
.Double
||
171 Type et
= t
.GetElementType();
172 if (et
.IsArray
) return false;
173 return TypeExpression
.TypeIsCLSCompliant(t
);
175 Object
[] attr
= CustomAttribute
.GetCustomAttributes(t
, typeof(CLSCompliantAttribute
), false);
177 return ((CLSCompliantAttribute
)attr
[0]).IsCompliant
;
180 attr
= CustomAttribute
.GetCustomAttributes(m
, typeof(CLSCompliantAttribute
), false);
182 return ((CLSCompliantAttribute
)attr
[0]).IsCompliant
;
184 Assembly a
= m
.Assembly
;
185 attr
= CustomAttribute
.GetCustomAttributes(a
, typeof(CLSCompliantAttribute
), false);
187 return ((CLSCompliantAttribute
)attr
[0]).IsCompliant
;